From 1211aeba0b1ca75ac1d6d5be0e8234541d52ae63 Mon Sep 17 00:00:00 2001 From: Factiven Date: Mon, 24 Apr 2023 14:48:02 +0700 Subject: initial commit on pre-dev --- pages/anime/[...id].js | 925 ++++++++++++++++++++++--------------------------- 1 file changed, 408 insertions(+), 517 deletions(-) (limited to 'pages/anime/[...id].js') diff --git a/pages/anime/[...id].js b/pages/anime/[...id].js index f58673d..cea025c 100644 --- a/pages/anime/[...id].js +++ b/pages/anime/[...id].js @@ -1,280 +1,359 @@ -import React, { useEffect, useState } from "react"; -import { META } from "@consumet/extensions"; +import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; +import "react-loading-skeleton/dist/skeleton.css"; -import Link from "next/link"; -import Layout from "../../components/layout"; import Head from "next/head"; - -import { closestMatch } from "closest-match"; +import Image from "next/image"; +import { useRouter } from "next/router"; +import { useEffect, useState } from "react"; +import Layout from "../../components/layout"; +import Link from "next/link"; import Content from "../../components/hero/content"; -import { getServerSession } from "next-auth/next"; -import { authOptions } from "../api/auth/[...nextauth]"; -import Image from "next/image"; +import { useSession } from "next-auth/react"; -export default function Himitsu({ - info, - color, - episodeList, - episode1, - sessions, - progress, - status, - lastPlayed, - stall, -}) { - const [showText, setShowtext] = useState(false); - const [load, setLoad] = useState(true); - const [showAll, setShowAll] = useState(false); - const [time, setTime] = useState(0); +const query = ` + query ($username: String, $status: MediaListStatus) { + MediaListCollection(userName: $username, type: ANIME, status: $status, sort: SCORE_DESC) { + user { + id + name + about (asHtml: true) + createdAt + avatar { + large + } + statistics { + anime { + count + episodesWatched + meanScore + minutesWatched + } + } + bannerImage + mediaListOptions { + animeList { + sectionOrder + } + } + } + lists { + status + name + entries { + id + mediaId + status + progress + score + media { + id + status + title { + english + romaji + } + episodes + coverImage { + large + } + } + } + } + } + } + `; + +export default function Info() { + const { data: session, status } = useSession(); + const [data, setData] = useState(null); + const [episode, setEpisode] = useState(null); + const [loading, setLoading] = useState(false); + const [progress, setProgress] = useState(null); + const [statuses, setStatuses] = useState(null); + const [stall, setStall] = useState(false); + const [color, setColor] = useState(null); - const episode = episodeList; - const epi1 = episode1; + const [showAll, setShowAll] = useState(false); - const maxItems = 3; + const [time, setTime] = useState(0); + const { id } = useRouter().query; - const nextAir = info.nextAiringEpisode; - // console.log(time); + // console.log(stall); useEffect(() => { - if (nextAir) { - setTime(convertSecondsToTime(nextAir.timeUntilAiring)); - } - - function getBrightness(color) { - const rgb = color.match(/\d+/g); - return (299 * rgb[0] + 587 * rgb[1] + 114 * rgb[2]) / 1000; - } + const defaultState = { + data: null, + episode: null, + loading: true, + statuses: null, + progress: null, + }; - // set the text color based on the background color - function setTextColor(element) { - const backgroundColor = getComputedStyle(element).backgroundColor; - const brightness = getBrightness(backgroundColor); - if (brightness < 128) { - element.style.color = "#fff"; // white + // Reset all state variables to their default values + Object.keys(defaultState).forEach((key) => { + const value = defaultState[key]; + if (Array.isArray(value)) { + value.length + ? eval( + `set${ + key.charAt(0).toUpperCase() + key.slice(1) + }(${JSON.stringify(value)})` + ) + : eval(`set${key.charAt(0).toUpperCase() + key.slice(1)}([])`); } else { - element.style.color = "#000"; // black + eval( + `set${key.charAt(0).toUpperCase() + key.slice(1)}(${JSON.stringify( + value + )})` + ); } - } - - const elements = document.querySelectorAll(".dynamic-text"); - elements.forEach((element) => { - setTextColor(element); }); + async function fetchData() { + if (id) { + setLoading(false); + try { + const res = await fetch( + `https://api.moopa.my.id/meta/anilist/info/${id?.[0]}` + ); + const data = await res.json(); + if (data.episodes.length === 0) { + const res = await fetch( + `https://api.consumet.org/meta/anilist/info/${id[0]}?provider=9anime` + ); + const datas = await res.json(); + setColor({ backgroundColor: `${data?.color || "white"}` }); + setStall(true); + setEpisode(datas.episodes); + } else { + setEpisode(data.episodes); + } + + setColor({ backgroundColor: `${data?.color || "white"}` }); + + if (session?.user?.name) { + const response = await fetch("https://graphql.anilist.co/", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + query: query, + variables: { + username: session?.user?.name, + }, + }), + }); + + const dat = await response.json(); + + const prog = dat.data.MediaListCollection; + + const gat = prog.lists.map((item) => item.entries); + const git = gat.map((item) => + item.find((item) => item.media.id === parseInt(data?.id)) + ); + const gut = git?.find( + (item) => item?.media.id === parseInt(data?.id) + ); + + if (gut) { + setProgress(gut?.progress); + if (gut.status === "CURRENT") { + setStatuses("Watching"); + } else if (gut.status === "PLANNING") { + setStatuses("Planned to watch"); + } else if (gut.status === "COMPLETED") { + setStatuses("Completed"); + } else if (gut.status === "DROPPED") { + setStatuses("Dropped"); + } else if (gut.status === "PAUSED") { + setStatuses("Paused"); + } else if (gut.status === "REPEATING") { + setStatuses("Rewatching"); + } + } + } + + if (data.nextAiringEpisode) { + setTime( + convertSecondsToTime(data.nextAiringEpisode.timeUntilAiring) + ); + } - setLoad(false); - }, [color, sessions, info.id]); + function getBrightness(color) { + const rgb = color.match(/\d+/g); + return (299 * rgb[0] + 587 * rgb[1] + 114 * rgb[2]) / 1000; + } + // set the text color based on the background color + function setTextColor(element) { + const backgroundColor = getComputedStyle(element).backgroundColor; + const brightness = getBrightness(backgroundColor); + if (brightness < 128) { + element.style.color = "#fff"; // white + } else { + element.style.color = "#000"; // black + } + } + + const elements = document.querySelectorAll(".dynamic-text"); + elements.forEach((element) => { + setTextColor(element); + }); + + setData(data); + setLoading(true); + } catch (error) { + setTimeout(() => { + window.location.reload(); + }, 1000); + } + } + // setLoading(true); + } + fetchData(); + }, [id, session?.user?.name]); + // console.log(episode); return ( <> - {info.title?.english || info.title.romaji} - - - + {data?.title?.romaji || data?.title?.english} - - -
-
-
- -
- {info ? ( -
-
-
-
-
- {info.image && ( - <> -
- image -
- + + +
+
+
+ {data && ( + banner anime + )} +
+
+
+
+ {loading ? ( + data && ( + <> +
+ poster anime + + ) + ) : ( + + )} +
+
+
+

+ {loading ? ( + data?.title?.romaji || data?.title?.english + ) : ( + )} -

- - {/* MOBILE */} -
-

- {info.title.romaji || info.title.english} -

-
-
-

Rate:

-

{info.rating}%

-
- -
-

Format:

-

{info.type}

-
- -
-

Status:

-

{info.status}

-
- - {/* {nextAir && ( -
-

Ep {nextAir.episode}:

-

{time}

-
- )} */} -
-
- {epi1 && epi1[0] ? ( - -

- - - {" "} - WATCH -

- - ) : ( -

- + {loading ? ( + data && ( +
+
+
- - {" "} - WATCH -

- )} -
-
-
- - {/* PC */} -
-
-

- {info.title?.english || - info.title.romaji || - info.title.native} -

-
-
- {episode && episode.length} Episodes -
-
- {info.releaseDate} -
-
- {info.rating}% -
-
- {info.type} -
-
- {info.status} -
-
- Sub | EN -
- {nextAir && ( -
- Ep {nextAir.episode}: {time} + {data?.totalEpisodes} Episodes +
+
+ {data?.releaseDate} +
+
+ {data?.rating}% +
+
+ {data?.type} +
+
+ {data?.status} +
+
+ Sub | EN +
+ {data && data.nextAiringEpisode && ( +
+ Ep {data.nextAiringEpisode.episode}: {time} +
+ )}
- )} -
-
-
-

-

-
-

- -

+
+ ) + ) : ( + + )}
+ {loading ? ( +

+ ) : ( + + )} + {/*

{data.description}

*/}
+
-
-
+
+
+ {data && (
Relations
- {info.relations.length > maxItems && ( -
setShowAll(!showAll)} - > - {showAll ? "show less" : "show more"} -
- )} -
-
- {info.relations && - info.relations - .slice(0, showAll ? info.relations.length : maxItems) + )} + {data?.relations?.length > 3 && ( +
setShowAll(!showAll)} + > + {showAll ? "show less" : "show more"} +
+ )} +
+
+ {loading + ? data?.relations && + data?.relations + .slice(0, showAll ? data?.relations.length : 3) .map((relation, index) => { return (
- {relation.id}
@@ -323,287 +404,97 @@ export default function Himitsu({
); - })} -
+ }) + : [1, 2, 3].map((item) => ( +
+ +
+ ))}
- -
-
+
+
+
+ {data && (

Episodes

-
- -
- -
- {status && ( - <> -
- {status} - - status - -
- - )} -
-
- {load ? ( -

Loading...

- ) : episode ? ( - episode.map((episode, index) => { - return ( -
- -

Episode {episode.number}

- {episode.title && ( -

- "{episode.title}" -

- )} - -
-
- ); - }) - ) : ( -

No Episodes Available

- )} -
+ )} + {statuses && ( + <> +
+ {statuses} + + status + +
+ + )}
+ {loading ? ( + data && ( +
+ {episode ? ( + episode.map((episode, index) => { + return ( +
+ +

Episode {episode.number}

+ {episode.title && ( +

+ "{episode.title}" +

+ )} + +
+
+ ); + }) + ) : ( +

No Episodes Available

+ )} +
+ ) + ) : ( + <> + )}
+
+ {data && (
-
- ) : ( -
-

- 404 -

-

{`> Woops.. I think we don't have that Anime :(`}

- - Return to search - -
- )} -
- + )} +
+
+
+ + ); } -export async function getServerSideProps(context) { - context.res.setHeader( - "Cache-Control", - "public, s-maxage=10, stale-while-revalidate=59" - ); - const session = await getServerSession(context.req, context.res, authOptions); - - const { id } = context.query; - if (!id) { - return { - notFound: true, - }; - } - - const provider = new META.Anilist(); - - const [info, episodes] = await Promise.all([ - fetch(`https://api.moopa.my.id/meta/anilist/info/${id[0]}`).then((res) => - res.json() - ), - provider.fetchEpisodesListById(id[0]), - ]); - - if (!info) { - return { - notFound: true, - }; - } - - let episodeList = episodes; - let stall = false; - - if (episodes.length === 0) { - const res = await fetch( - `https://api.consumet.org/meta/anilist/info/${id[0]}?provider=9anime` - ); - const data = await res.json(); - episodeList = data.episodes; - stall = true; - } - - let progress = null; - let status = null; - let lastPlayed = null; - - if (session) { - const response = await fetch("https://graphql.anilist.co/", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - query: ` - query ($username: String, $status: MediaListStatus) { - MediaListCollection(userName: $username, type: ANIME, status: $status, sort: SCORE_DESC) { - user { - id - name - about (asHtml: true) - createdAt - avatar { - large - } - statistics { - anime { - count - episodesWatched - meanScore - minutesWatched - } - } - bannerImage - mediaListOptions { - animeList { - sectionOrder - } - } - } - lists { - status - name - entries { - id - mediaId - status - progress - score - media { - id - status - title { - english - romaji - } - episodes - coverImage { - large - } - } - } - } - } - } - `, - variables: { - username: session?.user.name, - }, - }), - }); - - const dat = await response.json(); - - // const resp = await fetch(`/api/get-user?userName=${session?.user.name}`); - // const data = await resp.json(); - - lastPlayed = session?.user?.recentWatch?.filter( - (item) => item.title.romaji === info.title.romaji - )[0]?.episode; - - const prog = dat.data.MediaListCollection; - - const gat = prog.lists.map((item) => item.entries); - const git = gat.map((item) => - item.find((item) => item.media.id === parseInt(info.id)) - ); - const gut = git?.find((item) => item?.media.id === parseInt(info.id)); - - if (gut) { - progress = gut?.progress; - if (gut.status === "CURRENT") { - status = "Watching"; - } else if (gut.status === "PLANNING") { - status = "Planned to watch"; - } else if (gut.status === "COMPLETED") { - status = "Completed"; - } else if (gut.status === "DROPPED") { - status = "Dropped"; - } else if (gut.status === "PAUSED") { - status = "Paused"; - } else if (gut.status === "REPEATING") { - status = "Rewatching"; - } - } - } - - const color = { backgroundColor: `${info.color}` }; - const epi1 = episodes.filter((epi) => epi.number === 1); - const title = info.title?.userPreferred || "No Title"; - - return { - props: { - info: { - ...info, - title: { - ...info.title, - userPreferred: title, - }, - }, - color, - episodeList, - episode1: epi1, - sessions: session, - progress: progress || null, - status: status, - lastPlayed: lastPlayed || null, - stall, - }, - }; -} - function convertSecondsToTime(sec) { let days = Math.floor(sec / (3600 * 24)); let hours = Math.floor((sec % (3600 * 24)) / 3600); -- cgit v1.2.3 From fa3e2aeeb9894a133df5f79d97987c276c7f06a1 Mon Sep 17 00:00:00 2001 From: Factiven Date: Mon, 24 Apr 2023 23:43:05 +0700 Subject: Revamp UI 1 --- pages/anime/[...id].js | 381 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 269 insertions(+), 112 deletions(-) (limited to 'pages/anime/[...id].js') diff --git a/pages/anime/[...id].js b/pages/anime/[...id].js index cea025c..65e9568 100644 --- a/pages/anime/[...id].js +++ b/pages/anime/[...id].js @@ -1,6 +1,8 @@ import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; import "react-loading-skeleton/dist/skeleton.css"; +import { HeartIcon } from "@heroicons/react/20/solid"; + import Head from "next/head"; import Image from "next/image"; import { useRouter } from "next/router"; @@ -64,9 +66,76 @@ const query = ` } `; +const infoQuery = `query ($id: Int) { + Media(id: $id) { + id + type + title { + romaji + english + native + } + coverImage { + extraLarge + large + color + } + bannerImage + description + episodes + nextAiringEpisode { + episode + airingAt + } + averageScore + popularity + status + startDate { + year + } + duration + genres + relations { + edges { + relationType + node { + id + type + status + title { + romaji + english + userPreferred + } + coverImage { + extraLarge + large + color + } + } + } + } + recommendations { + nodes { + mediaRecommendation { + id + title { + romaji + } + coverImage { + extraLarge + large + } + } + } + } + } +}`; + export default function Info() { const { data: session, status } = useSession(); const [data, setData] = useState(null); + const [info, setInfo] = useState(null); const [episode, setEpisode] = useState(null); const [loading, setLoading] = useState(false); const [progress, setProgress] = useState(null); @@ -79,11 +148,17 @@ export default function Info() { const [time, setTime] = useState(0); const { id } = useRouter().query; - // console.log(stall); + const rec = info?.recommendations?.nodes.map( + (data) => data.mediaRecommendation + ); + + // console.log(rec); + console.log(progress); useEffect(() => { const defaultState = { data: null, + info: null, episode: null, loading: true, statuses: null, @@ -113,11 +188,30 @@ export default function Info() { if (id) { setLoading(false); try { - const res = await fetch( - `https://api.moopa.my.id/meta/anilist/info/${id?.[0]}` - ); + // const res = await fetch( + // `https://api.moopa.my.id/meta/anilist/info/${id?.[0]}` + // ); + + const [res, info] = await Promise.all([ + fetch(`https://api.moopa.my.id/meta/anilist/info/${id?.[0]}`), + fetch("https://graphql.anilist.co/", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + query: infoQuery, + variables: { + id: id?.[0], + }, + }), + }), + ]); const data = await res.json(); - if (data.episodes.length === 0) { + const infos = await info.json(); + setInfo(infos.data.Media); + + if (!data || data.episodes.length === 0) { const res = await fetch( `https://api.consumet.org/meta/anilist/info/${id[0]}?provider=9anime` ); @@ -218,111 +312,168 @@ export default function Info() { return ( <> - {data?.title?.romaji || data?.title?.english} + + {info + ? info?.title?.romaji || info?.title?.english + : "Retrieving Data..."} +
-
+
- {data && ( + {info ? ( banner anime + ) : ( +
)}
-
-
+
+ {/* Mobile */} + +
+
+

+ {/* Yuru Camp△ SEASON 2 */} + {info?.title?.romaji || info?.title?.english} +

+

+

+ {info?.genres + ?.slice( + 0, + info?.genres?.length > 3 ? info?.genres?.length : 3 + ) + .map((item, index) => ( + + + {item} + + {/* {index !== info?.genres?.length - 1 && ( + + )} */} + + ))} +
+ {info && ( +
+
+ {statuses ? statuses : "Add to List"} +
+
+ +
+
+ )} +
+
+
+ {/*
+ completed +
+
+ +
*/} +
+
+
+ + {/* PC */} +
- {loading ? ( - data && ( - <> -
- poster anime - - ) + {info ? ( + <> +
+ poster anime + ) : ( )}
-
+ + {/* PC */} +

- {loading ? ( - data?.title?.romaji || data?.title?.english + {info ? ( + info?.title?.romaji || info?.title?.english ) : ( )}

- {loading ? ( - data && ( -
-
-
- {data?.totalEpisodes} Episodes -
-
- {data?.releaseDate} -
-
- {data?.rating}% -
-
- {data?.type} -
-
- {data?.status} -
-
- Sub | EN -
- {data && data.nextAiringEpisode && ( -
- Ep {data.nextAiringEpisode.episode}: {time} -
- )} -
+ {info ? ( +
+
+ {info?.episodes} Episodes
- ) +
+ {info?.startDate?.year} +
+
+ {info?.averageScore}% +
+
+ {info?.type} +
+
+ {info?.status} +
+
+ Sub | EN +
+ {info && info.nextAiringEpisode && ( +
+ Ep {info.nextAiringEpisode.episode}: {time} +
+ )} +
) : ( )}
- {loading ? ( + {info ? (

) : ( @@ -333,12 +484,12 @@ export default function Info() {

- {data && ( + {info && (
Relations
)} - {data?.relations?.length > 3 && ( + {info?.relations?.edges?.length > 3 && (
setShowAll(!showAll)} @@ -350,43 +501,46 @@ export default function Info() {
- {loading - ? data?.relations && - data?.relations - .slice(0, showAll ? data?.relations.length : 3) - .map((relation, index) => { + {info?.relations?.edges + ? info?.relations?.edges + .slice(0, showAll ? info?.relations?.edges.length : 3) + .map((r, index) => { + const rel = r.node; return (
{relation.id}
- {relation.relationType} + {r.relationType}
- {relation.title.romaji} + {rel.title.userPreferred || + rel.title.romaji}
-
{relation.type}
+
{rel.type}
@@ -414,7 +569,7 @@ export default function Info() {
- {data && ( + {info && (

Episodes

@@ -445,7 +600,7 @@ export default function Info() { stall ? `9anime` : "" }`} className={`text-start text-sm md:text-lg ${ - episode.number <= progress + progress && episode.number <= progress ? "text-[#5f5f5f]" : "text-white" }`} @@ -454,7 +609,7 @@ export default function Info() { {episode.title && (

) ) : ( - <> +

+ Loading Episodes... +
)}
- {data && ( + {rec && (
)} -- cgit v1.2.3 From e4ec4f58812512314e270839baf90065541a348e Mon Sep 17 00:00:00 2001 From: Factiven Date: Tue, 25 Apr 2023 16:17:42 +0700 Subject: woosh woosh loading speed goes woosh --- pages/anime/[...id].js | 190 ++++++++++++++++++++++++++++++------------------- 1 file changed, 116 insertions(+), 74 deletions(-) (limited to 'pages/anime/[...id].js') diff --git a/pages/anime/[...id].js b/pages/anime/[...id].js index 65e9568..cf70c62 100644 --- a/pages/anime/[...id].js +++ b/pages/anime/[...id].js @@ -1,7 +1,12 @@ import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; import "react-loading-skeleton/dist/skeleton.css"; -import { HeartIcon } from "@heroicons/react/20/solid"; +import { ClockIcon, HeartIcon } from "@heroicons/react/20/solid"; +import { + TvIcon, + ArrowTrendingUpIcon, + RectangleStackIcon, +} from "@heroicons/react/24/outline"; import Head from "next/head"; import Image from "next/image"; @@ -153,7 +158,7 @@ export default function Info() { ); // console.log(rec); - console.log(progress); + // console.log(info); useEffect(() => { const defaultState = { @@ -188,10 +193,6 @@ export default function Info() { if (id) { setLoading(false); try { - // const res = await fetch( - // `https://api.moopa.my.id/meta/anilist/info/${id?.[0]}` - // ); - const [res, info] = await Promise.all([ fetch(`https://api.moopa.my.id/meta/anilist/info/${id?.[0]}`), fetch("https://graphql.anilist.co/", { @@ -211,19 +212,27 @@ export default function Info() { const infos = await info.json(); setInfo(infos.data.Media); + const textColor = setTxtColor(infos.data.Media.coverImage?.color); + if (!data || data.episodes.length === 0) { const res = await fetch( `https://api.consumet.org/meta/anilist/info/${id[0]}?provider=9anime` ); const datas = await res.json(); - setColor({ backgroundColor: `${data?.color || "white"}` }); + setColor({ + backgroundColor: `${data?.color || "#ffff"}`, + color: textColor, + }); setStall(true); setEpisode(datas.episodes); } else { setEpisode(data.episodes); } - setColor({ backgroundColor: `${data?.color || "white"}` }); + setColor({ + backgroundColor: `${data?.color || "#ffff"}`, + color: textColor, + }); if (session?.user?.name) { const response = await fetch("https://graphql.anilist.co/", { @@ -275,40 +284,19 @@ export default function Info() { ); } - function getBrightness(color) { - const rgb = color.match(/\d+/g); - return (299 * rgb[0] + 587 * rgb[1] + 114 * rgb[2]) / 1000; - } - - // set the text color based on the background color - function setTextColor(element) { - const backgroundColor = getComputedStyle(element).backgroundColor; - const brightness = getBrightness(backgroundColor); - if (brightness < 128) { - element.style.color = "#fff"; // white - } else { - element.style.color = "#000"; // black - } - } - - const elements = document.querySelectorAll(".dynamic-text"); - elements.forEach((element) => { - setTextColor(element); - }); - setData(data); setLoading(true); } catch (error) { + console.log(error); setTimeout(() => { window.location.reload(); }, 1000); } } - // setLoading(true); } fetchData(); }, [id, session?.user?.name]); - // console.log(episode); + return ( <> @@ -318,14 +306,18 @@ export default function Info() { : "Retrieving Data..."} - +
{info ? ( banner anime )}
-
+
{/* Mobile */} -
-
+
+

{/* Yuru Camp△ SEASON 2 */} {info?.title?.romaji || info?.title?.english}

-

+
{info?.genres ?.slice( 0, info?.genres?.length > 3 ? info?.genres?.length : 3 ) .map((item, index) => ( - - - {item} - + + {item} {/* {index !== info?.genres?.length - 1 && ( )} */} @@ -366,24 +360,38 @@ export default function Info() { ))}
{info && ( -
-
- {statuses ? statuses : "Add to List"} -
-
- +
+
+
+ {statuses ? statuses : "Add to List"} +
+
+ +
)}
-
-
- {/*
- completed -
-
- -
*/} +
+
+ {info && info.status !== "NOT_YET_RELEASED" ? ( + <> +
+ +

{info?.type}

+
+
+ +

{info?.averageScore}%

+
+
+ +

{info?.episodes} Episodes

+
+ + ) : ( +
{info && "Not Yet Released"}
+ )}
@@ -422,44 +430,44 @@ export default function Info() { {info ? (
{info?.episodes} Episodes
{info?.startDate?.year}
{info?.averageScore}%
{info?.type}
{info?.status}
Sub | EN
{info && info.nextAiringEpisode && (
Ep {info.nextAiringEpisode.episode}: {time} @@ -476,7 +484,7 @@ export default function Info() { className="overflow-y-scroll scrollbar-thin pr-2 scrollbar-thumb-secondary scrollbar-thumb-rounded-lg h-[140px]" /> ) : ( - + )} {/*

{data.description}

*/}
@@ -499,7 +507,7 @@ export default function Info() { )}
{info?.relations?.edges ? info?.relations?.edges @@ -574,9 +582,25 @@ export default function Info() { Episodes )} + {info?.nextAiringEpisode && ( +
+
+

Next Ep :

+
+ {time} +
+
+
+ +
+
+ )} {statuses && ( <> -
+
{statuses} status @@ -589,36 +613,38 @@ export default function Info() { data && (
{episode ? ( - episode.map((episode, index) => { + episode.map((epi, index) => { return (
-

Episode {episode.number}

- {episode.title && ( +

Episode {epi.number}

+ {epi.title && (

- "{episode.title}" + "{epi.title}"

)} -
+ {index !== episode?.length - 1 && ( + + )}
); }) @@ -673,3 +699,19 @@ function convertSecondsToTime(sec) { return time.trim(); } + +function getBrightness(hexColor) { + if (!hexColor) { + return 200; + } + const rgb = hexColor + .match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i) + .slice(1) + .map((x) => parseInt(x, 16)); + return (299 * rgb[0] + 587 * rgb[1] + 114 * rgb[2]) / 1000; +} + +function setTxtColor(hexColor) { + const brightness = getBrightness(hexColor); + return brightness < 150 ? "#fff" : "#000"; +} -- cgit v1.2.3